package com.hemerasolutions.v2trainer.controller;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;

import org.primefaces.event.NodeSelectEvent;
import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.TreeNode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.hemerasolutions.v2trainer.component.interfaces.detail.EquipmentDetailsCompInterface;
import com.hemerasolutions.v2trainer.component.interfaces.detail.ExerciseGroupDetailsCompInterface;
import com.hemerasolutions.v2trainer.component.interfaces.detail.ModalityDetailsCompInterface;
import com.hemerasolutions.v2trainer.component.interfaces.detail.TrainingDetailsCompInterface;
import com.hemerasolutions.v2trainer.component.interfaces.detail.TrainingSystemDetailsCompInterface;
import com.hemerasolutions.v2trainer.controller.interfaces.LibraryBeanInterface;
import com.hemerasolutions.v2trainer.model.exercise.Equipment;
import com.hemerasolutions.v2trainer.model.exerciseGroup.ExerciseGroup;
import com.hemerasolutions.v2trainer.model.library.Library;
import com.hemerasolutions.v2trainer.model.modality.Modality;
import com.hemerasolutions.v2trainer.model.training.Training;
import com.hemerasolutions.v2trainer.model.users.User;
import com.hemerasolutions.v2trainer.service.ExceptionService;
import com.hemerasolutions.v2trainer.service.interfaces.LibraryServiceInterface;
import com.hemerasolutions.v2trainer.service.interfaces.UserServiceInterface;

@Controller
@ManagedBean(name="libraryBean")
@Scope("view")
public class LibraryBean extends BaseBean implements LibraryBeanInterface {

	private static final long serialVersionUID = 1L;

	
	@Autowired
	private LibraryServiceInterface libraryService;

	@Autowired
	private UserServiceInterface userService;
	
	private TreeNode root;
	
	private int libraryViewType;
	
	private TreeNode[] selNodes;
	
	private Library library;
	
	private List<Object> memoryArea; 
	
	private List<Library> sharedLibrarys;
	
	private List<Library> ownLibrarys;

	private List<Library> publicLibrarys;
	
	private Modality modality;

	private Training training;
	
	private Training trainingSystem;
	
	private ExerciseGroup exerciseGroup;

	private Equipment equipment;

	private List<Library> librarys;

	@Autowired
	private ModalityDetailsCompInterface modalityDetailsComp;
	
	@Autowired
	private ExerciseGroupDetailsCompInterface exerciseGroupDetailsComp;
	
	@Autowired
	private TrainingSystemDetailsCompInterface trainingSystemDetailsComp;
	
	@Autowired
	private TrainingDetailsCompInterface trainingDetailsComp;
	
	@Autowired
	private EquipmentDetailsCompInterface equipmentDetailsComp;
	
	public LibraryBean() {
		super();
	}

	@PostConstruct
	public void init(){
		this.loadLibrary();
		this.memoryArea = new ArrayList<Object>();
	}

	public void loadLibrary() {
		this.sharedLibrarys = new ArrayList<Library>();
		this.ownLibrarys = new ArrayList<Library>();
		this.publicLibrarys = new ArrayList<Library>();
		this.librarys = new ArrayList<Library>();

		for(Library lib: this.getActiveUserAllowedLibrarys()){
			if(lib.getOwner().equals(this.getActiveUser())){
				if(lib.getShareType() == Library.SHARE_TYPE_PERSONAL){
					this.ownLibrarys.add(lib);
				}else if(	lib.getShareType() == Library.SHARE_TYPE_AFFLIATES ||
							lib.getShareType() == Library.SHARE_TYPE_AFFLIATES){
					this.sharedLibrarys.add(lib);
				}else if(lib.getShareType() == Library.SHARE_TYPE_PUBLIC){
					this.sharedLibrarys.add(lib);
				}
			}else{
				this.publicLibrarys.add(lib);
			}
		}
		
		root = new DefaultTreeNode("Root", null);  
        TreeNode libraryRoot = new DefaultTreeNode("root",this.localizedText("Librarys"), root);

        this.createLibraryNode("shared", this.localizedText("Shared"),libraryRoot, this.sharedLibrarys);
        this.createLibraryNode("personal", this.localizedText("Personal"),libraryRoot, this.ownLibrarys);
        this.createLibraryNode("public", this.localizedText("Public"),libraryRoot, this.publicLibrarys);
        
   		libraryRoot.setExpanded(true);  
	}        
        
	private void createLibraryNode(String typeName, String localizedText,
			TreeNode root, List<Library> librarys) {

        TreeNode node = new DefaultTreeNode(typeName,localizedText, root);
		
		
		for(Library library:librarys){

			TreeNode libraryNode = new DefaultTreeNode("library",library, node);

			DefaultTreeNode modalitysNode 		= new DefaultTreeNode("modalitys",this.localizedText("Modalitys"), libraryNode);  
			DefaultTreeNode trainingSystemsNode = new DefaultTreeNode("trainingSystems",this.localizedText("TrainingSystems"), libraryNode);  
			DefaultTreeNode exerciseGroupsNode	= new DefaultTreeNode("exerciseGroups",this.localizedText("ExerciseGroups"), libraryNode);  
			DefaultTreeNode trainingsNode 		= new DefaultTreeNode("trainings",this.localizedText("Trainings"), libraryNode);  
			DefaultTreeNode equipmentsNode 		= new DefaultTreeNode("equipments",this.localizedText("Equipments"), libraryNode);  
			
			for(Modality modality:library.getVersionableModalitys()){
				new DefaultTreeNode("modality",modality,modalitysNode);
			}
			
			for(Training  training: library.getTrainings()){
				if(training.isTrainingSystem()){
					new DefaultTreeNode("trainingSystem",training,trainingSystemsNode);
				}else{
					new DefaultTreeNode("training",training,trainingsNode);
				}
			}
			
			for(ExerciseGroup eg:library.getExerciseGroups()){
				new DefaultTreeNode("exerciseGroup",eg,exerciseGroupsNode);
			}
			
			
			for(Equipment equipment:library.getEquipments()){
				new DefaultTreeNode("equipment",equipment,equipmentsNode);
			}
		}
		
		node.setExpanded(true);
		
		
	}

	public void toDeleteLibrary(){

		this.library = (Library)this.selNodes[this.selNodes.length - 1].getData();
		
		if(!this.getActiveUser().equals(this.library.getOwner())){
			this.showErrorMessage(this.localizedText("Error"), this.localizedText("CannotDeleteOtherUsersLibrarys"));			
		}else{
			this.executeJavascript("wconfExcLibrary.show();");
		}
	}
	
	public void deleteLibrary(){
		try{
			User logged = this.getActiveUser();
			logged.getLibrarys().remove(this.library);
			userService.saveUser(logged);
			this.showInfoMessage(	this.localizedText("Deleted"),
					this.localizedText("LibraryDeletedWithSuccess"));
			this.loadLibrary();
			this.library = null;
		}catch(ExceptionService e){
			this.showErrorMessage(this.localizedText("DeleteError"),
					e.getLocalizedMessage());
		}		
				
	}

	public void onNodeSelect(NodeSelectEvent event){

		String type = event.getTreeNode().getType();
		
		if(type.equals("library")){
			this.libraryViewType = 1;
			this.library = (Library)event.getTreeNode().getData();
		
		}else if(type.equals("modality")){
			this.libraryViewType = 2;
			this.modality = (Modality)event.getTreeNode().getData();
			this.modalityDetailsComp.setModality(this.modality);
			this.modalityDetailsComp.refresh();
			
		}else if(type.equals("training")){
			this.libraryViewType = 3;
			this.training = (Training)event.getTreeNode().getData();
			this.trainingDetailsComp.setTraining(training);
			this.trainingDetailsComp.refresh();
			
		}else if(type.equals("trainingSystem")){
			this.libraryViewType = 4;
			this.trainingSystem = (Training)event.getTreeNode().getData();
			this.trainingSystemDetailsComp.setTrainingSystem(this.trainingSystem);
			this.trainingSystemDetailsComp.refresh();
			
		}else if(type.equals("exerciseGroup")){
			this.libraryViewType = 5;
			this.exerciseGroup = (ExerciseGroup)event.getTreeNode().getData();
			this.exerciseGroupDetailsComp.setExerciseGroup(this.exerciseGroup);
			this.exerciseGroupDetailsComp.refresh();
			
		}else if (type.equals("equipment")){
			this.libraryViewType = 6;
			this.equipment = (Equipment)event.getTreeNode().getData();
			this.equipmentDetailsComp.setEquipment(this.equipment);
			this.equipmentDetailsComp.refresh();
		}
	}		

	
	public void createLibrary(){
		
		User logged = this.getActiveUser();

		for(Library lib:logged.getLibrarys()){
			if(lib.getName().equals(this.library.getName())){
				this.showErrorMessage(this.localizedText("SaveError"), this.localizedText("ThereIsAlreadyAEntryWithThisName"));		
				return;	
			}
		}

		for(Library lib:logged.getLibrarys()){
			if(lib.isDefaultLibrary() && this.library.isDefaultLibrary()){
				lib.setDefaultLibrary(false);
			}
		}
		
		
		logged.getLibrarys().add(this.library);
		this.updateUserLibrary(logged);
		this.loadLibrary();
		this.libraryViewType = 7;
	
	}

	private void updateUserLibrary(User logged) {
		try{
			userService.saveUser(logged);
			this.showInfoMessage(	this.localizedText("SavedWithSuccess"),
					this.localizedText("TheLibrary") + " " +
					this.library.getName() + " " + 
					this.localizedText("wasSavedWithSuccess"));		
						
		}catch(Exception ex){
			this.showErrorMessage(this.localizedText("SaveError"), ex.getLocalizedMessage());		
		}
	}

	public void saveLibrary(){
		User logged = this.getActiveUser();

		for(int i = 0; i < logged.getLibrarys().size();i++){
			if(logged.getLibrarys().get(i).getId() == this.library.getId()){
				logged.getLibrarys().set(i, this.library);
			}
		}
		

		for(Library lib:logged.getLibrarys()){
			if( lib.isDefaultLibrary() && this.library.isDefaultLibrary() && lib != this.library){
				lib.setDefaultLibrary(false);
			}
		}
		
		this.updateUserLibrary(logged);
		this.loadLibrary();
		this.libraryViewType = 7;
		
	}
	
	public void toAddLibrary(){
		this.library = new Library(this.getActiveUser());
	}
	
	public void toEditLibrary(){
	
		Library lib = (Library)this.selNodes[this.selNodes.length - 1].getData();
		
		if( !lib.getOwner().equals(this.getActiveUser()) &&
			! ( 	lib.getOwner().getUserType() == User.USERTYPE_ADMIN &&
			 		this.getActiveUserType() == User.USERTYPE_ADMIN	)){
			this.showErrorMessage(this.localizedText("EditError"), this.localizedText("EditError"));
			this.showInfoMessage(	this.localizedText("Tip"),this.localizedText("MakeAOwnCopyToEdit"));			
			return;
		}
		
		this.library = (Library)this.selNodes[this.selNodes.length - 1].getData();

	}
	
	
	public void toCopy(){
		for(TreeNode tNode:this.selNodes){
			this.memoryArea.add(tNode.getData());
		}
	}
	
	
	public void paste(){
		if(this.selNodes[this.selNodes.length - 1].getType().equals("equipments")){
			for(Object obj:this.memoryArea){
				if(obj instanceof Equipment){
					Library lib = this.getLibraryOfNode(this.selNodes[this.selNodes.length - 1]);
					lib.getEquipments().add(new Equipment ((Equipment) obj));
				}
			}
			
		}else if(this.selNodes[this.selNodes.length - 1].getType().equals("modalitys")){
			
		}else if(this.selNodes[this.selNodes.length - 1].getType().equals("trainingSystems")){
			
		}else if(this.selNodes[this.selNodes.length - 1].getType().equals("trainings")){
			
		}else if(this.selNodes[this.selNodes.length - 1].getType().equals("exerciseGroups")){
			
		}else if(this.selNodes[this.selNodes.length - 1].getType().equals("librarys")){

		}else if(this.selNodes[this.selNodes.length - 1].getType().equals("shared")){
			
			
		}
	}
	
	public void cancelChange(){
		
	}
	
	public Equipment copyEquipment(Equipment equip) {
		this.equipment = new Equipment();
		
		return null;
	}

	private Library getLibraryOfNode(TreeNode currentNode) {
		
		if(currentNode.getType().equals("library")){
			return (Library)currentNode.getData();
		}else{
			if(currentNode.getParent().equals("library")){
				return (Library)currentNode.getParent().getData();
			}else if(currentNode.getParent().getParent().equals("library")){
				return (Library)currentNode.getParent().getParent().getData();
			}
		}
		
		return null;
	}

	public TreeNode getRoot() {
		return root;
	}


	public int getLibraryViewType() {
		return libraryViewType;
	}



	public void setRoot(TreeNode root) {
		this.root = root;
	}


	public void setLibraryViewType(int libraryViewType) {
		this.libraryViewType = libraryViewType;
	}


	public Modality getModality() {
		return modality;
	}

	public Training getTrainingSystem() {
		return trainingSystem;
	}

	public ExerciseGroup getExerciseGroup() {
		return exerciseGroup;
	}

	public Training getTraining() {
		return training;
	}

	public Library getLibrary() {
		return library;
	}

	public void setModality(Modality modality) {
		this.modality = modality;
	}

	public void setTrainingSystem(Training  trainingSystem) {
		this.trainingSystem = trainingSystem;
	}

	public void setExerciseGroup(ExerciseGroup exerciseGroup) {
		this.exerciseGroup = exerciseGroup;
	}

	public void setTraining(Training training) {
		this.training = training;
	}

	public void setLibrary(Library library) {
		this.library = library;
	}

	public Equipment getEquipment() {
		return equipment;
	}

	public void setEquipment(Equipment equipment) {
		this.equipment = equipment;
	}
	public List<Library> getSharedLibrarys() {
		return sharedLibrarys;
	}

	public void setSharedLibrarys(List<Library> librarys) {
		this.sharedLibrarys = librarys;
	}

	public List<Library> getOwnLibrarys() {
		return ownLibrarys;
	}

	public void setOwnLibrarys(List<Library> ownLibrarys) {
		this.ownLibrarys = ownLibrarys;
	}

	public TreeNode[] getSelNodes() {
		return selNodes;
	}

	public void setSelNodes(TreeNode[] selNodes) {
		this.selNodes = selNodes;
	}

	public List<Library> getLibrarys() {
		return librarys;
	}

	public void setLibrarys(List<Library> librarys) {
		this.librarys = librarys;
	}

	public ModalityDetailsCompInterface getModalityDetailsComp() {
		return modalityDetailsComp;
	}

	public void setModalityDetailsComp(
			ModalityDetailsCompInterface modalityDetailsComp) {
		this.modalityDetailsComp = modalityDetailsComp;
	}

	public ExerciseGroupDetailsCompInterface getExerciseGroupDetailsComp() {
		return exerciseGroupDetailsComp;
	}

	public void setExerciseGroupDetailsComp(
			ExerciseGroupDetailsCompInterface exerciseGroupDetailsComp) {
		this.exerciseGroupDetailsComp = exerciseGroupDetailsComp;
	}

	public TrainingSystemDetailsCompInterface getTrainingSystemDetailsComp() {
		return trainingSystemDetailsComp;
	}

	public void setTrainingSystemDetailsComp(
			TrainingSystemDetailsCompInterface trainingSystemDetailsComp) {
		this.trainingSystemDetailsComp = trainingSystemDetailsComp;
	}

	public TrainingDetailsCompInterface getTrainingDetailsComp() {
		return trainingDetailsComp;
	}

	public void setTrainingDetailsComp(
			TrainingDetailsCompInterface trainingDetailsComp) {
		this.trainingDetailsComp = trainingDetailsComp;
	}

	public EquipmentDetailsCompInterface getEquipmentDetailsComp() {
		return equipmentDetailsComp;
	}

	public void setEquipmentDetailsComp(
			EquipmentDetailsCompInterface equipmentDetailsComp) {
		this.equipmentDetailsComp = equipmentDetailsComp;
	}

	
	
	
}


